package com.atguigu.spzx.cart.service.impl;

import com.atguigu.spzx.cart.service.CartService;
import com.atguigu.spzx.common.consts.SpzxConsts;
import com.atguigu.spzx.common.util.AuthUtil;
import com.atguigu.spzx.model.entity.cart.CartItem;
import com.atguigu.spzx.model.entity.product.ProductSku;
import com.atguigu.spzx.model.entity.user.UserInfo;
import com.atguigu.spzx.model.exception.SpzxException;
import com.atguigu.spzx.model.vo.common.Result;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.product.client.ServiceProductClient;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {
    @Resource
    RedisTemplate redisTemplate;
    @Resource
    ServiceProductClient serviceProductClient;
    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        //1、获取当前用户的购物车(hash结构)
        UserInfo userInfo = AuthUtil.getUserInfo();
        Long userId = userInfo.getId();
        // spzx:cart:userId   因为redisTemplate键和属性序列化器配置的都是字符串序列化器，所以不能存Long
        BoundHashOperations<String,String, CartItem> cart = redisTemplate
                .boundHashOps(SpzxConsts.SPZX_CART_PREFIX+userId);
        CartItem cartItem = cart.get(String.valueOf(skuId));
        if(cartItem!=null){
             //2、如果购物车中已存在skuId的购物项，更新数量加上skuNum
             cartItem.setSkuNum(cartItem.getSkuNum()+skuNum);
             cartItem.setUpdateTime(new Date());

        }else{
            //3、如果购物车中不存在skuId的购物项，创建skuId对应的购物项，数量为skuNum存入到购物车中
            cartItem = new CartItem();
            cartItem.setSkuId(skuId);
            cartItem.setSkuNum(skuNum);
            cartItem.setUserId(userId);
            cartItem.setIsChecked(1);//默认选中
            cartItem.setCreateTime(new Date());
            cartItem.setUpdateTime(new Date());

            // 需要根据skuId查询
            /*
                sku的数据保存在product服务连接的数据库中
                所以cart服务添加购物车的业务需要远程访问 product服务接口才能查询到需要的数据
                1、分布式架构的所有微服务都注册到同一个注册中心同一个名称空间分组内：nacos注册中心
                2、服务提供方： product服务新增根据skuId查询购物车需要的商品详情接口
                        2.1 将服务提供者和消费者都需要使用的实体类抽取到model模块中： spzx-model
                        2.2 服务提供方为自己要暴露给消费者的接口 开发一个单独的feignclient模块，编写feign客户端
                3、服务消费者：cart服务 整合feignclient模块
                        注入feign客户端 调用方法发起远程调用就可以查询到数据
             */
            // 远程调用接收到远程服务响应的json时，默认转为LinkedHashMap
            Result<ProductSku> result = serviceProductClient.getSkuBySkuId(skuId);
            if(result.getCode().intValue() != 200){
                throw new SpzxException(ResultCodeEnum.ERROR);
            }
            ProductSku productSku = result.getData();
            cartItem.setCartPrice(productSku.getSalePrice());
            cartItem.setSkuName(productSku.getSkuName());
            cartItem.setImgUrl(productSku.getThumbImg());

        }
        //更新或者新增redis中skuId对应的购物项： skuId必须转为字符串
        cart.put(String.valueOf(skuId) ,cartItem );
    }

    @Override
    public List<CartItem> cartList() {
        BoundHashOperations<String, String, CartItem> hashOps = getCart();
        return hashOps.values();
    }

    @Override
    public void deleteCartItem(Long skuId) {
        BoundHashOperations<String, String, CartItem> cart = getCart();
        cart.delete(String.valueOf(skuId));
    }

    @Override
    public void clearCart() {
        UserInfo userInfo = AuthUtil.getUserInfo();
        Long userId = userInfo.getId();
        //根据键删除用户的购物车hash结构
        redisTemplate.delete(SpzxConsts.SPZX_CART_PREFIX + userId);
    }

    @Override
    public void checkCart(Long skuId, Integer status) {
        BoundHashOperations<String, String, CartItem> cart = getCart();
        CartItem cartItem = cart.get(String.valueOf(skuId));
        cartItem.setIsChecked(status);

        cart.put(String.valueOf(skuId) , cartItem);
    }

    @Override
    public void allCheckCart(Integer status) {
        BoundHashOperations<String, String, CartItem> cart = getCart();
        cart.entries().forEach((skuIdStr,cartItem)->{
            //修改选中状态
            cartItem.setIsChecked(status);
            //更新到redis中
            cart.put(skuIdStr , cartItem);
        });
    }

    @Override
    public List<CartItem> allCheckedCart() {
        BoundHashOperations<String, String, CartItem> cart = getCart();
        List<CartItem> cartItems = cart.values().stream().filter(cartItem -> cartItem.getIsChecked().intValue() == 1)
                .collect(Collectors.toList());
        return cartItems;
    }

    private BoundHashOperations<String, String, CartItem> getCart() {
        UserInfo userInfo = AuthUtil.getUserInfo();
        Long userId = userInfo.getId();
        BoundHashOperations<String,String,CartItem> hashOps = redisTemplate
                .boundHashOps(SpzxConsts.SPZX_CART_PREFIX + userId);
        return hashOps;
    }
}
